﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using YJKRGeometry;
using SectionSignAndFilled.StairsClearHeightDimension;
using SectionSignAndFilled.StairsRoomPlanSign.ControlLayer;

namespace SectionSignAndFilled.StairsRoomPlanSign.ModelLayer
{
	public class FlatRoofPacker : BaseShapePacker
	{
		public double ThisElevation
		{
			get
			{
				return this.m_dThisElevation;
			}
			private set
			{
				this.m_dThisElevation = value;
			}
		}

		public List<StairsRunPacker> LstLinkeRun
		{
			get
			{
				return this.m_lstLinkeRun;
			}
			private set
			{
				this.m_lstLinkeRun = value;
			}
		}

		public FlatRoofPacker(double inputElevation, Element inputElement, List<Curve> inputLstCurve, List<StairsRunPacker> lstInputPackers) : base(inputElement, inputLstCurve)
		{
			this.LstLinkeRun.AddRange(lstInputPackers);
			this.ThisElevation = inputElevation;
			if (this.ThisElevation < SignManger.ThisStairPlandDataPacker.NowViewZ)
			{
				base.ViewKind = ShapeViewKindEnum.Total;
			}
			else if (this.ThisElevation > SignManger.ThisStairPlandDataPacker.NowViewZ)
			{
				base.ViewKind = ShapeViewKindEnum.None;
			}
			else
			{
				base.ViewKind = ShapeViewKindEnum.Cut;
			}
			this.UpdataMidPoint();
		}

		public FlatRoofPacker(StairsLanding input, RevitLinkInstance inputRevitLinkInstance = null) : base(input, FlatRoofPacker.GetStairsLandingCurves(input))
		{
			Transform transform = null;
			if (inputRevitLinkInstance != null)
			{
				transform = inputRevitLinkInstance.GetTransform();
			}
			BoundingBoxXYZ boundingBoxXYZ = input.get_BoundingBox(null);
			double z = Geometry.TransformPoint(boundingBoxXYZ.Min, transform).Z;
			this.ThisElevation = z + input.BaseElevation;
		}

		public override void UpdataThisShapeByView(ViewData inputData)
		{
			if (this.ThisElevation < inputData.CutHeightZ)
			{
				base.ViewKind = ShapeViewKindEnum.Total;
				return;
			}
			if (this.ThisElevation > inputData.CutHeightZ)
			{
				base.ViewKind = ShapeViewKindEnum.None;
				return;
			}
			base.ViewKind = ShapeViewKindEnum.Cut;
		}

		public bool IfRunLinkThis(StairsRunPacker inputRun)
		{
			bool flag = false;
			StairsLanding stairsLanding = base.ThisElement as StairsLanding;
			IList<StairsComponentConnection> connections = stairsLanding.GetConnections();
			foreach (StairsComponentConnection stairsComponentConnection in connections)
			{
				if (stairsComponentConnection.PeerElementId == inputRun.ThisStairsRun.Id)
				{
					flag = true;
					this.LstLinkeRun.Add(inputRun);
					break;
				}
			}
			if (flag)
			{
				this.LstLinkeRun.Add(inputRun);
				this.UpdataMidPoint();
			}
			return flag;
		}

		public override bool TryGetAPathInShape(XYZ startPoint, XYZ endPoint, double useZ, out List<Curve> lstPathes)
		{
			lstPathes = new List<Curve>();
			List<XYZ> list = new List<XYZ>();
			StairsRunPacker stairsRunPacker;
			Line line;
			this.FindNearRun(out stairsRunPacker, out line);
			Line line2 = Line.CreateUnbound(base.MidPoint, Utility.GetAVerticalVector(line.Direction, false));
			list.Add(startPoint);
			list.Add(line2.Project(startPoint).XYZPoint);
			list.Add(line2.Project(endPoint).XYZPoint);
			list.Add(endPoint);
			for (int i = 0; i < list.Count - 1; i++)
			{
				lstPathes.Add(Line.CreateBound(list[i], list[i + 1]));
			}
			return true;
		}

		public bool TryGetALevelDimension(out LevelDimensionPacker levelDimensionPacker)
		{
			bool result;
			try
			{
				levelDimensionPacker = new LevelDimensionPacker(base.MidPoint, this.ThisElevation);
				result = true;
			}
			catch
			{
				levelDimensionPacker = null;
				result = false;
			}
			return result;
		}

		private void UpdataMidPoint()
		{
			StairsRunPacker stairsRunPacker;
			Line line;
			this.FindNearRun(out stairsRunPacker, out line);
			XYZ xyz = line.Evaluate(0.5, true);
			Line line2 = Line.CreateUnbound(xyz, Utility.GetAVerticalVector(stairsRunPacker.LstDriection[0], false));
			List<XYZ> list = new List<XYZ>();
			foreach (StairsRunPacker run in this.LstLinkeRun)
			{
				Line line3 = this.FindVetcorLine(run);
				if (null != line3)
				{
					list.Add(line3.Evaluate(0.5, true));
				}
			}
			if (list.Count > 0)
			{
				base.MidPoint = StairsClearHeightDimensionGeometry.CalculatMidPoint(list);
			}
			base.MidPoint = line2.Project(base.MidPoint).XYZPoint;
		}

		private void FindNearRun(out StairsRunPacker useRun, out Line minDistanceLine)
		{
			double maxValue = double.MaxValue;
			useRun = null;
			minDistanceLine = null;
			foreach (StairsRunPacker stairsRunPacker in this.LstLinkeRun)
			{
				Line line = this.FindVetcorLine(stairsRunPacker);
				if (null != line && line.Length < maxValue)
				{
					minDistanceLine = line;
					useRun = stairsRunPacker;
				}
			}
		}

		private Line FindVetcorLine(StairsRunPacker run)
		{
			Line result = null;
			IntersectionResultArray intersectionResultArray = new IntersectionResultArray();
			List<XYZ> list = new List<XYZ>();
			XYZ xyz = null;
			XYZ xyz2 = null;
			foreach (Curve curve in base.LstAllShapeCurve)
			{
				Line line = run.LstUsePath[0].Clone() as Line;
				line.MakeUnbound();
				SetComparisonResult setComparisonResult = curve.Intersect(line, out intersectionResultArray);
				if (setComparisonResult == SetComparisonResult.Overlap)
				{
					list.Add(intersectionResultArray.get_Item(0).XYZPoint);
				}
			}
			XYZ xyz3 = null;
			double val = double.MaxValue;
			foreach (XYZ xyz4 in list)
			{
				for (int i = 0; i < 2; i++)
				{
					if (Geometry.LessThan(xyz4.DistanceTo(run.LstUsePath[0].GetEndPoint(i)), val))
					{
						val = xyz4.DistanceTo(run.LstUsePath[0].GetEndPoint(i));
						xyz3 = xyz4;
					}
				}
			}
			xyz = xyz3;
			if (xyz != null)
			{
				double maxValue = double.MaxValue;
				foreach (XYZ xyz5 in list)
				{
					if (xyz5.DistanceTo(xyz) < maxValue && !xyz5.IsAlmostEqualTo(xyz))
					{
						xyz2 = xyz5;
					}
				}
			}
			try
			{
				result = Line.CreateBound(xyz, xyz2);
			}
			catch
			{
			}
			return result;
		}

		public static List<Curve> GetStairsLandingCurves(StairsLanding input)
		{
			List<Curve> list = new List<Curve>();
			foreach (Curve item in input.GetFootprintBoundary().ToList<Curve>())
			{
				list.Add(item);
			}
			return list;
		}

		private double m_dThisElevation;

		private List<StairsRunPacker> m_lstLinkeRun = new List<StairsRunPacker>();
	}
}
